package com.github.util;

import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.spring.SpringUtil;
import com.github.bean.ServeUserAccount;
import com.github.bean.ServerUserSession;
import com.github.common.constant.MyConstant;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.web.socket.WebSocketSession;

import java.io.IOException;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;


@Slf4j
public class SessionSocketHolder {
    //
    public static final ConcurrentHashMap<String, ServerUserSession> serverUserSessionMap =
            new ConcurrentHashMap<>();
    public static final ConcurrentHashMap<String, ServeUserAccount> serverUserAccountMap =
            new ConcurrentHashMap<>();
    // deviceID 1为拉手  2 语音 3插卡

    public static void removeAll() throws IOException {
        for (ServerUserSession session : serverUserSessionMap.values()) {
            if (session.isOnline()) {
                session.getSession().close();
            }
        }
        serverUserSessionMap.clear();
        serverUserAccountMap.clear();
    }

    public static List<String> getAllAccount() {
        List<String> accountList = new ArrayList<>();
        for (String key : serverUserSessionMap.keySet()) {
            if (StrUtil.isNotBlank(key)) {
                String[] split = key.split(":");
                accountList.add(split[0]);
            }
        }
        return accountList;
    }

    public static void put(String account, String deviceType, WebSocketSession webSession) {
        ServerUserSession serverUser = new ServerUserSession();
        serverUser.setAccount(account);
        serverUser.setDeviceType(deviceType);
        serverUser.setSession(webSession);
        serverUser.setLastHeartbeatTime(System.currentTimeMillis());
        serverUserSessionMap.put(account + ":" + deviceType, serverUser);
        ServeUserAccount serveUserAccount = new ServeUserAccount();
        serveUserAccount.setAccount(account);
        serveUserAccount.setDeviceType(deviceType);
        serverUserAccountMap.put(webSession.getId(), serveUserAccount);
    }

    public static ServerUserSession get(String sessionId) {
        ServeUserAccount serveUserAccount = serverUserAccountMap.get(sessionId);
        if (serveUserAccount == null) {
            return null;
        }
        return serverUserSessionMap.get(serveUserAccount.getAccount() + ":" + serveUserAccount.getDeviceType());
    }

    public static Boolean isOpen(ServerUserSession session) {
        if (session == null) {
            return false;
        }
        return session.getSession().isOpen();
    }

    public static Boolean isOpen(String account, String deviceType) {
        ServerUserSession serverUserSession = serverUserSessionMap.get(account + ":" + deviceType);
        if (serverUserSession == null) {
            return false;
        }
        return serverUserSession.getSession().isOpen();
    }


    public static List<ServerUserSession> getByAccount(String account) {
        return Arrays.asList(
                serverUserSessionMap.get(account + ":" + Role.SERVER),
                serverUserSessionMap.get(account + ":" + Role.CALL),
                serverUserSessionMap.get(account + ":" + Role.VOICE)
        ).stream()
                .filter(Objects::nonNull) // 过滤掉null值
                .collect(Collectors.toList());
    }

    public static ServerUserSession get(String account, Integer deviceType) {
        return serverUserSessionMap.get(account + ":" + deviceType);
    }

    public static ServerUserSession get(String account, String deviceType) {
        return serverUserSessionMap.get(account + ":" + deviceType);
    }

    public static void remove(String sessionId) {
        ServeUserAccount serveUserAccount = serverUserAccountMap.get(sessionId);
//        log.info("remove, serveUserAccount={}", serveUserAccount);
        if (serveUserAccount != null) {
            StringRedisTemplate stringRedisTemplate = SpringUtil.getBean(StringRedisTemplate.class);
            Object object = stringRedisTemplate.opsForHash().get(MyConstant.UserInfoCache, serveUserAccount.getAccount());
            boolean isHave = object == null;
//            log.info("remove, account={}, isHave={}", serveUserAccount.getAccount(), isHave);
            if (isHave) //账号不在缓存里面
                serverUserSessionMap.remove(serveUserAccount.getAccount() + ":" + serveUserAccount.getDeviceType());
        }
        serverUserAccountMap.remove(sessionId);
    }

    public static void close(ServerUserSession session) {
        if (session == null) {
            return;
        }
        if (session.isOnline()) {
            try {
                session.getSession().close();
            } catch (IllegalStateException e) {
            } catch (IOException e) {
                log.info("session关闭异常, sessionId={} ,account={}", session.getSession().getId(), session.getAccount());
            }
        }
    }

    public static List<ServerUserSession> getAllUserSession() {
        Collection<ServerUserSession> values = serverUserSessionMap.values();
        return new ArrayList<>(values);
    }
}
